﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;

namespace Silverlight3dApp.Learning.Lesson04
{
    public class SpriteManager : DrawableGameComponent
    {
        private SpriteBatch _spriateBatch;
        private UserControlledSprite _player;
        private readonly List<AutomatedSprite> _sprites = new List<AutomatedSprite>();

        private readonly Random _random = new Random();

        private int _enemySpawnMinMilliseconds = 1000;
        private int _enemySpawnMaxMilliseconds = 2000;
        private int _enemyMinSpeed = 2;
        private int _enemyMaxSpeed = 8;
        private int _nextSpawnTime;

        public SpriteManager(Game game) : base(game)
        {
        }

        public Vector2 PlayerPosition
        {
            get
            {
                return _player.Position;
            }
        }

        public override void Initialize()
        {
            ResetSpawnTime();
            base.Initialize();
        }

        private void ResetSpawnTime()
        {
            _nextSpawnTime = _random.Next(_enemySpawnMinMilliseconds, _enemySpawnMaxMilliseconds);
        }

        protected override void LoadContent()
        {
            _spriateBatch = new SpriteBatch(Game.GraphicsDevice);
            _player = new UserControlledSprite(Game.Content.Load<Texture2D>(@"Images/threerings"), Vector2.Zero, new Vector2(75, 75), 10, new Vector2(0, 0), new Vector2(6, 8), new Vector2(5, 5));
            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            _nextSpawnTime -= gameTime.ElapsedGameTime.Milliseconds;
            if (_nextSpawnTime < 0)
            {
                SpawnEnemy();
                ResetSpawnTime();
            }

            var bounds = Game.GraphicsDevice.Viewport.Bounds;
            _player.Update(gameTime, bounds);
            foreach (var sprite in _sprites.ToArray())
            {
                sprite.Update(gameTime, bounds);
                if (sprite.CollisionRectangle.Intersects(_player.CollisionRectangle))
                {
                    sprite.PlayCollisionSound();
                    _sprites.Remove(sprite);
                }
                if (sprite.IsOutOfBounds(bounds))
                {
                    _sprites.Remove(sprite);
                }
            }
            base.Update(gameTime);
        }

        private void SpawnEnemy()
        {
            var frameSize = new Vector2(75, 75);
            var position = new Vector2(_random.Next(0, (int) (Game.GraphicsDevice.Viewport.Width - frameSize.X)), _random.Next(0, (int) (Game.GraphicsDevice.Viewport.Height - frameSize.Y)));
            var speed = new Vector2(_random.Next(_enemyMinSpeed, _enemyMaxSpeed), _random.Next(_enemyMinSpeed, _enemyMaxSpeed));

            switch (_random.Next(3))
            {
                case 0:
                    _sprites.Add(new BouncingSprite(Game.Content.Load<Texture2D>(@"Images/skullball"), position, frameSize, 10, new Vector2(0, 0), new Vector2(6, 8), speed, Game.Content.Load<SoundEffect>(@"Audios/skullcollision")));
                    break;
                case 1:
                    _sprites.Add(new ChasingSprite(Game.Content.Load<Texture2D>(@"Images/skullball"), position, frameSize, 10, new Vector2(0, 0), new Vector2(6, 8), speed, Game.Content.Load<SoundEffect>(@"Audios/skullcollision"), this));
                    break;
                case 2:
                    _sprites.Add(new EvadingSprite(Game.Content.Load<Texture2D>(@"Images/skullball"), position, frameSize, 10, new Vector2(0, 0), new Vector2(6, 8), speed, Game.Content.Load<SoundEffect>(@"Audios/skullcollision"), this, 100));
                    break;
            }
        }

        public override void Draw(GameTime gameTime)
        {
            _spriateBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
            _player.Draw(gameTime, _spriateBatch);
            foreach (var sprite in _sprites)
            {
                sprite.Draw(gameTime, _spriateBatch);
            }
            _spriateBatch.End();
            base.Draw(gameTime);
        }
    }
}